package com.hf.eagle.web.base;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.upload.FormFile;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.ebiz.ssi.web.struts.BaseSsiAction;
import com.ebiz.ssi.web.struts.bean.UploadFile;
import com.hf.eagle.domain.SysModule;
import com.hf.eagle.service.Facade;
import com.hf.eagle.utils.EncryptUtilsV2;
import com.hf.eagle.utils.StringHelper;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.jimi.core.JimiException;

public abstract class BaseAction extends BaseSsiAction {

	private Facade facade;

	/**
	 * the powerful method to return facade with all services(method)
	 * 
	 * @return facade
	 */
	protected Facade getFacade() {
		return this.facade;
	}

	public void setServlet(ActionServlet actionServlet) {
		super.setServlet(actionServlet);
		Assert.notNull(actionServlet, "actionServlet is can not be null");
		ServletContext servletContext = actionServlet.getServletContext();
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
		this.facade = (Facade) wac.getBean("facade");
	}

	protected void setNaviStringToScope(HttpServletRequest request) {
		String mod_id = request.getParameter("mod_id");

		List<SysModule> naviList = new ArrayList<SysModule>();

		if (StringUtils.isNotBlank(mod_id)) {
			getNaviListFromSysModule(naviList, mod_id);
		}

		String naviString = StringHelper.getNaviStringFromSysModuleList(naviList);

		request.setAttribute("naviString", naviString);
	}

	private void getNaviListFromSysModule(List<SysModule> list, String mod_id) {
		SysModule sysModule = new SysModule();
		sysModule.setMod_id(new Long(mod_id));
		sysModule.setIs_del(0);
		sysModule = this.facade.getSysModuleService().getSysModule(sysModule);
		if (null != sysModule && sysModule.getPar_id() != 0) {
			list.add(sysModule);

			getNaviListFromSysModule(list, sysModule.getPar_id().toString());
		}
	}

	@SuppressWarnings("unchecked")
	protected List<UploadFile> uploadFileForWorkExplain(ActionForm form, String uploadDir) throws Exception {

		String ctxDir = getServlet().getServletContext().getRealPath(String.valueOf(File.separatorChar));
		if (!ctxDir.endsWith(String.valueOf(File.separatorChar))) {
			ctxDir = ctxDir + File.separatorChar;
		}
		File savePath = new File(ctxDir + uploadDir);

		logger.debug("savePath:" + savePath);

		if (!savePath.exists()) {
			savePath.mkdirs();
		}

		List<UploadFile> uploadFileList = new ArrayList<UploadFile>();
		UploadFile uploadFile = null;

		int i = 0;
		Hashtable fileh = form.getMultipartRequestHandler().getFileElements();

		for (Enumeration e = fileh.keys(); e.hasMoreElements();) {
			String key = (String) e.nextElement();

			FormFile formFile = (FormFile) fileh.get(key);
			String filename = formFile.getFileName().trim();
			if (!"".equals(filename)) {
				uploadFile = new UploadFile();
				uploadFile.setContentType(formFile.getContentType());
				uploadFile.setFileSize(formFile.getFileSize());
				uploadFile.setFileName(formFile.getFileName().trim());
				uploadFile.setFormName(key);

				String fileSaveName = formFile.getFileName().trim();
				String fileSavePath = uploadDir + fileSaveName;

				uploadFile.setFileSaveName(formFile.getFileName().trim());
				uploadFile.setFileSavePath(StringUtils.replace(uploadDir, String.valueOf(File.separatorChar), "/"));

				logger.debug(uploadFile.toString());

				uploadFileList.add(uploadFile);

				InputStream ins = formFile.getInputStream();
				OutputStream os = new FileOutputStream(ctxDir + fileSavePath);
				int bytesRead = 0;
				byte[] buffer = new byte[8192];
				while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
					os.write(buffer, 0, bytesRead);
				}
				os.close();
				ins.close();
			}
			i++;
		}
		return uploadFileList;
	}

	public void encodeCharacterForGetMethod(Object object, HttpServletRequest request) throws Exception {
		if (!StringUtils.equalsIgnoreCase(request.getMethod(), "GET")) {
			return;
		}

		if (object instanceof DynaBean) {
			DynaBean dynaBean = (DynaBean) object;
			DynaProperty origDescriptors[] = dynaBean.getDynaClass().getDynaProperties();
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if (getBeanUtilsBean().getPropertyUtils().isWriteable(dynaBean, name)) {
					Object value = dynaBean.get(name);
					if (value instanceof String) {
						getBeanUtilsBean().copyProperty(dynaBean, name, URLDecoder.decode(value.toString(), "UTF-8"));
					}
				}
			}
		} else {// is a standard JavaBean
			PropertyDescriptor origDescriptors[] = getBeanUtilsBean().getPropertyUtils().getPropertyDescriptors(object);
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if ("class".equals(name)) {
					continue; // No point in trying to set an object's class
				}
				if (getBeanUtilsBean().getPropertyUtils().isReadable(object, name)
						&& getBeanUtilsBean().getPropertyUtils().isWriteable(object, name)) {
					Object value = getBeanUtilsBean().getPropertyUtils().getSimpleProperty(object, name);
					if (value instanceof String) {
						getBeanUtilsBean().copyProperty(object, name, URLDecoder.decode(value.toString(), "UTF-8"));
					}
				}
			}
		}
	}

	public BeanUtilsBean getBeanUtilsBean() {
		return BeanUtilsBean.getInstance();
	}

	protected void renderExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String hiddenHtml = StringUtils.lowerCase(request.getParameter("hiddenHtml"));

		hiddenHtml = StringUtils.replace(hiddenHtml, "border=0", "border=1");
		hiddenHtml = StringUtils.replace(hiddenHtml, "border=\"0\"", "border=\"1\"");

		String fname = EncryptUtilsV2.encodingFileName(request.getParameter("hiddenName"));

		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + fname);

		PrintWriter out = response.getWriter();
		out.println(hiddenHtml);

		out.flush();
		out.close();
	}

	protected void renderExcelWithEncoding(HttpServletRequest request, HttpServletResponse response, String encoding)
			throws IOException {
		String hiddenHtml = StringUtils.lowerCase(request.getParameter("hiddenHtml"));

		hiddenHtml = StringUtils.replace(hiddenHtml, "border=0", "border=1");
		hiddenHtml = StringUtils.replace(hiddenHtml, "border=\"0\"", "border=\"1\"");

		String fname = EncryptUtilsV2.encodingFileName(request.getParameter("hiddenName"));

		response.setCharacterEncoding(encoding);// UTF-8 GBK
		response.setContentType("application/octet-stream");
		response.setHeader("Content-Disposition", "attachment;filename=" + fname);

		PrintWriter out = response.getWriter();
		out.println(hiddenHtml);

		out.flush();
		out.close();
	}

	@SuppressWarnings("unchecked")
	protected List<UploadFile> uploadFile(ActionForm form, String uploadDir, boolean isResizeImage,
			int... resizeVersions) throws Exception {
		if (StringUtils.isBlank(uploadDir)) {
			uploadDir = StringUtils.join(new String[] { "files", "upload", "" }, File.separator);
		}

		String[] folderPatterns = new String[] { "yyyy", "MM", "dd", "" };
		String autoCreatedDateDir = DateFormatUtils
				.format(new Date(), StringUtils.join(folderPatterns, File.separator));
		String ctxDir = getServlet().getServletContext().getRealPath(File.separator);
		if (!ctxDir.endsWith(File.separator)) {
			ctxDir = ctxDir + File.separator;
		}
		File savePath = new File(ctxDir + uploadDir + autoCreatedDateDir);
		logger.info("===> save path is: {}", savePath);
		if (!savePath.exists()) {
			savePath.mkdirs();
		}

		List<UploadFile> uploadFileList = new ArrayList<UploadFile>();
		UploadFile uploadFile = null;

		Hashtable fileh = form.getMultipartRequestHandler().getFileElements();

		for (Enumeration e = fileh.keys(); e.hasMoreElements();) {
			String key = (String) e.nextElement();

			FormFile formFile = (FormFile) fileh.get(key);
			String fileName = formFile.getFileName().trim();
			if (!"".equals(fileName)) {
				uploadFile = new UploadFile();
				uploadFile.setContentType(formFile.getContentType());
				uploadFile.setFileSize(formFile.getFileSize());
				uploadFile.setFileName(formFile.getFileName().trim());
				uploadFile.setFormName(key);
				String fileSaveName = StringUtils.join(new String[] { UUID.randomUUID().toString(), ".",
						uploadFile.getExtension() });
				String fileSavePath = uploadDir + autoCreatedDateDir + fileSaveName;
				uploadFile.setFileSaveName(fileSaveName);
				uploadFile.setFileSavePath(StringUtils.replace(fileSavePath, File.separator, "/"));
				logger.info(uploadFile.toString());
				uploadFileList.add(uploadFile);

				String file_original_path = ctxDir + StringUtils.substringBeforeLast(fileSavePath, ".") + "_original."
						+ StringUtils.substringAfterLast(fileSavePath, ".");
				InputStream ins = formFile.getInputStream();
				OutputStream os = new FileOutputStream(file_original_path);
				int bytesRead = 0;
				byte[] buffer = new byte[8192];
				while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
					os.write(buffer, 0, bytesRead);
				}
				os.close();
				ins.close();

				// resize image
				if (isResizeImage && formFile.getContentType().indexOf("image/") != -1 && resizeVersions.length == 2) {
					resizeImageByFixed(file_original_path, ctxDir + fileSavePath, resizeVersions[0], resizeVersions[1]);
				}
			}
		}
		return uploadFileList;
	}

	public String resizeImageByFixed(String source, String desc, int width, int height) throws IOException,
			JimiException {
		if (StringUtils.isBlank(desc)) {
			desc = StringUtils.substringBeforeLast(source, ".") + "_small."
					+ StringUtils.substringAfterLast(source, ".");
		}

		Image sourceImage = ImageIO.read(new File(source));
		double sourceImageWidth = sourceImage.getWidth(null);
		double sourceImageHeight = sourceImage.getHeight(null);
		int resizedWidth = (int) sourceImageWidth;
		int resizedHeight = (int) sourceImageHeight;

		if (sourceImageWidth > width && sourceImageHeight > height) {
			double ratio = 0.0d;
			if (sourceImageHeight > sourceImageWidth) {
				ratio = height / sourceImageHeight;
			} else {
				ratio = width / sourceImageWidth;
			}

			resizedWidth = (int) (sourceImageWidth * ratio);
			resizedHeight = (int) (sourceImageHeight * ratio);
		} else if (sourceImageWidth > width && sourceImageHeight < height) {
			resizedHeight = (int) ((sourceImageHeight / sourceImageWidth) * width);
			resizedWidth = width;
		} else if (sourceImageHeight > height && sourceImageWidth < width) {
			resizedWidth = (int) ((sourceImageWidth / sourceImageHeight) * height);
			resizedHeight = height;
		} else {
			resizedWidth = (int) sourceImageWidth;
			resizedHeight = (int) sourceImageHeight;
		}

		if (resizedWidth > width) {
			resizedWidth = width;
		}
		if (resizedHeight > height) {
			resizedHeight = height;
		}

		BufferedImage bi = new BufferedImage(resizedWidth, resizedHeight, BufferedImage.TYPE_INT_RGB);
		bi.getGraphics().drawImage(sourceImage.getScaledInstance(resizedWidth, resizedHeight, Image.SCALE_SMOOTH), 0,
				0, null);

		FileOutputStream out = new FileOutputStream(desc);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(bi);
		out.close();

		return desc;
	}

	public String resizeByFixedHeight(String source, String desc, int fixedHeight) throws JimiException, IOException {
		if (StringUtils.isBlank(desc)) {
			desc = StringUtils.substringBeforeLast(source, ".") + "_small."
					+ StringUtils.substringAfterLast(source, ".");
		}

		Image sourceImage = ImageIO.read(new File(source));
		double sourceImageWidth = sourceImage.getWidth(null);
		double sourceImageHeight = sourceImage.getHeight(null);

		int resizedWidth = (int) ((sourceImageWidth / sourceImageHeight) * fixedHeight);

		BufferedImage bi = new BufferedImage(resizedWidth, fixedHeight, BufferedImage.TYPE_INT_RGB);
		bi.getGraphics().drawImage(sourceImage.getScaledInstance(resizedWidth, fixedHeight, Image.SCALE_SMOOTH), 0, 0,
				null);

		FileOutputStream out = new FileOutputStream(desc);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(bi);
		out.close();

		return desc;
	}

	public String resizeByFixedWidth(String source, String desc, int fixedWidth) throws JimiException, IOException {
		if (StringUtils.isBlank(desc)) {
			desc = StringUtils.substringBeforeLast(source, ".") + "_small."
					+ StringUtils.substringAfterLast(source, ".");
		}

		Image sourceImage = ImageIO.read(new File(source));
		double sourceImageWidth = sourceImage.getWidth(null);
		double sourceImageHeight = sourceImage.getHeight(null);

		int resizedHeight = (int) ((sourceImageHeight / sourceImageWidth) * fixedWidth);

		BufferedImage bi = new BufferedImage(fixedWidth, resizedHeight, BufferedImage.TYPE_INT_RGB);
		bi.getGraphics().drawImage(sourceImage.getScaledInstance(fixedWidth, resizedHeight, Image.SCALE_SMOOTH), 0, 0,
				null);

		FileOutputStream out = new FileOutputStream(desc);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(bi);
		out.close();

		return desc;
	}
}